package com.atguigu.exam.service.impl;

import com.atguigu.exam.entity.AnswerRecord;
import com.atguigu.exam.entity.ExamRecord;
import com.atguigu.exam.entity.Paper;
import com.atguigu.exam.entity.Question;
import com.atguigu.exam.mapper.AnswerRecordMapper;
import com.atguigu.exam.mapper.ExamRecordMapper;
import com.atguigu.exam.service.ExamService;
import com.atguigu.exam.service.KimiAiService;
import com.atguigu.exam.service.PaperService;
import com.atguigu.exam.vo.GradingResult;
import com.atguigu.exam.vo.StartExamVo;
import com.atguigu.exam.vo.SubmitAnswerVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.filefilter.FalseFileFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.Normalizer;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 考试服务实现类
 */
@Service
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class ExamServiceImpl extends ServiceImpl<ExamRecordMapper, ExamRecord> implements ExamService {

    @Autowired
    private AnswerRecordMapper answerRecordMapper;

    @Autowired
    private PaperService paperService;

    @Autowired
    private KimiAiService kimiAiService;

    @Override
    public ExamRecord startExam(StartExamVo startExamVo) {
//        1.检查是否已存在未完成的考试记录
        LambdaQueryWrapper<ExamRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ExamRecord::getExamId,startExamVo.getPaperId())
                .eq(ExamRecord::getStudentName,startExamVo.getStudentName())
                .eq(ExamRecord::getStatus,"进行中");

        ExamRecord exstingRecord = this.getOne(wrapper);
        if (exstingRecord != null){
            return exstingRecord; //如果有，直接返回
        }
//        2.创建新的考试记录
        ExamRecord examRecord = new ExamRecord();
        examRecord.setExamId(startExamVo.getPaperId());
        examRecord.setStartTime(LocalDateTime.now());
        examRecord.setStatus("进行中");
        examRecord.setScore(0); //将初始分数设置为0
        examRecord.setWindowSwitches(0); //将切换窗口次数设置为0；
        examRecord.setStudentName(startExamVo.getStudentName());
        this.save(examRecord);
        return examRecord;
    }

    @Transactional
    @Override
    public void submitAnswer(Integer examRecordId, List<SubmitAnswerVo> answers) {
//        1.查找考试记录
        ExamRecord examRecord = this.getById(examRecordId);
        if (examRecord == null || !"进行中".equals(examRecord.getStatus())){
            throw new RuntimeException("考试记录不存在或已完成");
        }
//        2.保存每一条答案
        List<AnswerRecord> answerRecords = new ArrayList<>(answers.size());
        answers.forEach(answerVo -> {
            AnswerRecord answerRecord = new AnswerRecord(examRecordId, answerVo.getQuestionId(), answerVo.getUserAnswer());
            answerRecords.add(answerRecord);
        });
//        自定义插入答案记录的方法：
        answerRecordMapper.insertBatchSomeColumn(answerRecords);
//        3.更新考试记录状态为"已完成"
        examRecord.setEndTime(LocalDateTime.now());
        examRecord.setStatus("已完成"); //已完成
        this.updateById(examRecord);

//        4.自动调用ai判卷
        log.info("试卷提交完成，开始自动ai智能判卷，考试记录id:{}",examRecordId);
        try {
//            进行判卷
            this.gradeExam(examRecordId);
            log.info("自动AI判卷完成，考试记录ID:{}",examRecordId);
        }catch (Exception e){
            log.error("自动AI判卷失败，考试记录ID:{}，错误:{}",examRecordId,e.getMessage());
//            判卷失败不影响提交，但记录错误

        }
    }

    @Override
    public ExamRecord getExamRecordDetail(Integer examRecordId) {
//        1.获取考试记录基本信息
        ExamRecord examRecord = this.getById(examRecordId);
        if (examRecord == null){
            log.error("考试记录不存在！");
            throw new RuntimeException("考试记录不存在！");
        }

//        2.如果考试记录存在，加载试卷信息（包含题目列表）
        Paper paper = paperService.getPaperWithQuestions(examRecord.getExamId());
        examRecord.setPaper(paper);

//        3.加载答题记录
        List<AnswerRecord> answerRecords = answerRecordMapper.selectList(new QueryWrapper<AnswerRecord>().eq("exam_record_id", examRecordId));
        if (paper != null && paper.getQuestions() != null && !answerRecords.isEmpty()){
            List<Long> questionOrder = paper.getQuestions().stream().map(Question::getId).toList();
//      先通过 map() 完成元素转换（Question → Long）,再通过 toList() 把转换后的元素收集成列表
            answerRecords.sort((a,b)->{ //对答题记录按题目顺序排序
                int idxA = questionOrder.indexOf(a.getQuestionId().longValue());
                int idxB = questionOrder.indexOf(b.getQuestionId().longValue());
                return Integer.compare(idxA,idxB); //按索引大小排序，小的排前面
            });
        }
        //最终记录考试答案：
        examRecord.setAnswerRecords(answerRecords);
        return examRecord;
    }

    /**
     * ai自动判卷方法
     * @param examRecordId
     */
    public ExamRecord gradeExam(Integer examRecordId) {
        log.info("开始ai智能判卷，考试记录ID:{}",examRecordId);

//        1.获取考试记录和所有答案记录
        ExamRecord examRecord = this.getById(examRecordId);
        if (examRecord == null){
            throw new RuntimeException("考试记录不存在！");
        }

        if (!"已完成".equals(examRecord.getStatus())){
            throw new RuntimeException("考试尚未完成，无法批阅！");
        }
//        查询考试记录下的所有回答：
        List<AnswerRecord> answerRecords = answerRecordMapper.selectList(new LambdaQueryWrapper<AnswerRecord>().eq(AnswerRecord::getExamRecordId, examRecordId));
//        考试回答为null，就是0分，修改状态为“已批阅”
        if (answerRecords.isEmpty()){
            log.warn("考试记录ID:{}没有找到答案记录",examRecordId);
            examRecord.setScore(0);
            examRecord.setStatus("已批阅！");
            this.updateById(examRecord);
            return examRecord;
        }

//        2.获取试卷中的所有题目及其分值
        Paper paper = paperService.getPaperWithQuestions(examRecord.getExamId());
        if (paper == null || paper.getQuestions() == null){
            throw new RuntimeException("试卷信息不完整！");
        }

        Map<Long, Question> questionMap = new java.util.HashMap<>();
//        paper.getQuestions()：从试卷对象中获取该试卷包含的所有题目列表（List<Question>）。
//        .forEach(...)：遍历这个题目列表，对每个题目执行后面的操作。
//        q -> questionMap.put(q.getId(), q)：这是一个 lambda 表达式，意思是：
//        对于列表中的每个题目对象 q，
//        调用 q.getId() 获取该题的唯一 ID 作为键，
//        把题目对象 q 本身作为值，
//        存入 questionMap 这个 Map 集合中。
        paper.getQuestions().forEach(q->questionMap.put(q.getId(),q));

        Integer totalScore = 0;
        Integer correctCount = 0;

        log.info("开始逐题判卷，共{}道题",answerRecords.size());

//        3.使用ai判卷（简答题），其余类型直接判卷！
        for (AnswerRecord record : answerRecords) {
            Question question = questionMap.get(record.getQuestionId().longValue());
            if (question == null){
                log.warn("题目id:{}在试卷中不存在，跳过",record.getQuestionId());
                continue;
            }

//            获取题目满分：
            Integer maxScore = question.getPaperScore() != null ? question.getPaperScore().intValue() : 10;
//            添加try-catch进行判卷，以免单道题影响整体逻辑
            try {
                if ("CHOICE".equals(question.getType()) || "JUDGE".equals(question.getType())){ //如果是选择题和判断题，直接答案对比
//                    客观题：直接对比标准答案：
                    String userAnswer = record.getUserAnswer() != null ? record.getUserAnswer().trim() : "";
                    String standardAnswer = question.getAnswer() != null ? question.getAnswer().getAnswer().trim() : "";

//                    对于判断题，需要处理T/F与True/ False的映射
                    if ("JUDGE".equals(question.getType())){
//                        统一转换为true/false格式进行比较
                        userAnswer = normalizeJudgeAnswer(userAnswer);
                        standardAnswer = normalizeJudgeAnswer(standardAnswer);
                    }
//                    进行答案对比：
                    if (userAnswer.equals(standardAnswer)){
                        record.setScore(maxScore);
                        record.setIsCorrect(1); //完全正确
                        record.setAiCorrection(null); //选择题和判断题不设置ai评语
                        correctCount++;
                    }else { //答案错误
                        record.setScore(0);
                        record.setIsCorrect(0);
                        record.setAiCorrection(null);
                    }
                    log.info("客观题判卷完成，题目ID:{},用户答案:{},标准答案:{},得分:{}/{}",question.getId(),record.getUserAnswer(),question.getAnswer().getAnswer(),record.getScore(),maxScore);
                }else if ("TEXT".equals(question.getType())){
//                    如果是简单题，需要调用kimi进行判卷
                    //todo：ai返回阅卷成绩：
                    GradingResult gradingResult =kimiAiService.gradeQuestion(question, record.getUserAnswer(), maxScore);
                    record.setScore(gradingResult.getScore());
                    record.setAiCorrection(gradingResult.getFeedback());

//                    给ai阅卷结果设置正确性标记:
                    if (gradingResult.getScore().equals(maxScore)){
                        record.setIsCorrect(1); //完全正确
                        correctCount++;
                    }else if (gradingResult.getScore() >0 ){
                        record.setIsCorrect(2); //部分正确
                    } else {
                        record.setIsCorrect(0); //错误
                    }
                    log.info("主观题ai判卷完成，题目ID:{},得分:{}/{}",question.getId(),gradingResult.getScore(),maxScore);
                }
                totalScore += record.getScore();
            }catch (Exception e){
                log.error("判卷失败，题目ID:{},错误:{}",question.getId(),e.getMessage());
                record.setScore(0);
                record.setIsCorrect(0);
                record.setAiCorrection("系统判卷失败，请联系管理员");
            }
//            更新答案记录：
            answerRecordMapper.updateById(record);
        }
        //todo:进行ai评语生成
        String examSummary = kimiAiService.generateExamSummary(totalScore,paper.getTotalScore().intValue(),answerRecords.size(),correctCount);

//        5.更新考试记录：
        examRecord.setScore(totalScore);
        examRecord.setStatus("已批阅");
        examRecord.setAnswers(examSummary); //将ai总评存储在answer字段中
        this.updateById(examRecord);
        log.info("AI智能判卷完成，考试记录ID:{},总分:{}/{}",examRecordId,totalScore,paper.getTotalScore());
        return examRecord;
    }

    /**
     * 标准化判断题答案，将T/F转换为true/false
     * @param answer
     * @return
     */
    private String normalizeJudgeAnswer(String answer) {
        if (answer == null || answer.trim().isEmpty()){
            return "";
        }
        String normalized = answer.trim().toUpperCase();
        switch (normalized){
            case "T":
            case "TRUE":
            case "正确":
                return "TRUE";
            case "F":
            case "FALSE":
            case "错":
                return "FALSE";
            default:
                return normalized;

        }
    }

}